package com.solcoo.merchant.base.task;

import java.lang.ref.WeakReference;
import java.util.Map;

import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.android.common.App;
import com.android.common.network.HttpDownloader;
import com.android.common.network.HttpResult;
import com.android.common.util.ArrayUtil;
import com.android.common.util.DialogUtil;
import com.android.common.util.StringUtil;
import com.android.common.util.ToastUtil;
import com.solcoo.merchant.ApplicationExt;
import com.solcoo.merchant.model.BaseDO;

/**
 * 
 * 提供异步的网络请求封装类
 * 
 * @author panjunlin
 * 
 */
public class TaskHelper {

	private static final String TAG = "TaskHelper";

	public static <T extends IHttpResultWapper> void loadView(Context context,
			String url, Callback<T> callback, Class<T> clazz) {
		new NetworkLoadView<T>(context, callback, clazz).execute(url);
	}

	public static <T extends IHttpResultWapper> void oper(Context context,
			String url, Callback<T> callback, Class<T> clazz) {
		new NetworkOper<T>(context, callback, clazz).execute(url);
	}

	public static <T extends IHttpResultWapper> void oper(Context context,
			String url, Callback<T> callback, Class<T> clazz,
			Map<String, Object> params) {
		new NetworkOper<T>(context, callback, clazz).execute(url, params);
	}

	public static <T> T syncGet(String url, Class<T> type) {
		HttpResult result = HttpDownloader.getConnectData(url);
		if (result.isSuccess() && result.data != null && result.data.length > 0) {
			return JSON.parseObject(result.data, type);
		} else {
			sendMessage(result.fromContext, result.resultCode);
			return null;
		}
	}

	public interface IHttpResultWapper {
		boolean isSuccess();
	}

	public interface Callback<T> {
		void onSuccess(T result);

		void onFail(T result);
	}

	public abstract static class DefaultCallback<T extends BaseDO> implements
			Callback<T> {
		private WeakReference<Context> mContext;

		public DefaultCallback(Context context) {
			mContext = new WeakReference<Context>(context);
		}

		public void onFail(T result) {
			Context c = mContext.get();
			if (c != null && result != null) {
				ToastUtil.showToast(c, result.failMsg);
			}
		}
	}

	private static class NetworkLoadView<T extends IHttpResultWapper> extends
			LoadViewAsyncTask<String, Void, T> {

		Callback<T> mCallback;

		Class<T> type;

		public NetworkLoadView(Context context, Callback<T> callback,
				Class<T> clazz) {
			super(context);
			mCallback = callback;
			type = clazz;
		}

		@Override
		protected T doInBackground(String... params) {
			HttpResult result = HttpDownloader.getConnectData(params[0]);
			if (result.isSuccess() && result.data != null
					&& result.data.length > 0) {
				return json2Object(mContext, result.data, type, false);
			} else if (result.resultCode == HttpResult.API_RESULT_NETWORK_CLOSE) {
				sendMessage(mContext.toString(),
						HttpResult.API_RESULT_NETWORK_CLOSE);
				return null;
			} else {
				return null;
			}
		}

		@Override
		protected void onPostExecute(T result) {
			super.onPostExecute(result);
			if (result.isSuccess()) {
				mCallback.onSuccess(result);
			} else {
				onNullData();
			}
		}

		@Override
		protected void onNullData() {
			super.onNullData();
		}

		@Override
		protected LoadViewAsyncTask<String, Void, T> clone() {
			LoadViewAsyncTask<String, Void, T> newTask = new NetworkLoadView<T>(
					mContext, mCallback, type);
			newTask.setParams(getParams());
			return newTask;
		}

	}

	private static class NetworkOper<T extends IHttpResultWapper> extends
			BindContextAsyncTask<Object, Void, T> {

		Callback<T> mCallback;

		Class<T> type;

		public NetworkOper(Context context, Callback<T> callback, Class<T> clazz) {
			super(context);
			mCallback = callback;
			type = clazz;
		}

		@SuppressWarnings("unchecked")
		@Override
		protected T doInBackground(Object... params) {
			Map<String, Object> mapParams = (Map<String, Object>) ArrayUtil
					.get(params, 1);
			String url = StringUtil.objectToString(params[0]);
			HttpResult result = null;
			if (mapParams != null) {
				result = HttpDownloader.postConnectData(url, mapParams);
			} else {
				result = HttpDownloader.getConnectData(url);
			}

			if (result.isSuccess() && result.data != null
					&& result.data.length > 0) {
				Log.v(TAG, "NetworkOper result:" + new String(result.data));
				return json2Object(mContext, result.data, type, true);
			} else {
				sendMessage(result.fromContext, result.resultCode);
				return null;
			}
		}

		@Override
		protected void onPostExecute(T result) {
			super.onPostExecute(result);
			if (result == null) {
				return;
			}
			if (result != null && result.isSuccess()) {
				mCallback.onSuccess(result);
			} else {
				mCallback.onFail(result);
			}
		}

		@Override
		public long getTimeOut() {
			return LONG_TIME_OUT;
		}
	}

	private static void sendMessage(String contextName, int code) {
		Message msg = netWorkHandler.obtainMessage(code);
		msg.obj = contextName;
		netWorkHandler.sendMessage(msg);
	}

	private static Handler netWorkHandler = new Handler(
			App.CONTEXT.getMainLooper()) {
		@Override
		public void handleMessage(Message msg) {
			String fromContext = msg.obj.toString();
			Context context = ApplicationExt.getInstance().getCurrentContext();
			switch (msg.what) {
			case HttpResult.API_RESULT_NETWORK_CLOSE:
				DialogUtil.createDialog(context, onWifiSettingClickListener,
						null, null, "亲,网络连接不可用,请设置", "网络设置").show();
				break;
			case HttpResult.API_RESULT_NETWORK_TIMEOUT:
				ToastUtil.showToastMsg(fromContext, "网络超时，请重试");
				break;
			default:
				ToastUtil.showToastMsg(fromContext, "网络异常，请重试");
				break;
			}
		}
	};

	private static OnClickListener onWifiSettingClickListener = new OnClickListener() {
		@Override
		public void onClick(DialogInterface dialog, int which) {
			dialog.dismiss();
			Intent intent = new Intent("android.settings.SETTINGS");
			ApplicationExt.getInstance().getCurrentContext()
					.startActivity(intent);
		}
	};

	private static <E> E json2Object(Context context, byte[] data,
			Class<E> type, boolean isShowToast) {
		E resultObject = null;
		try {
			resultObject = JSON.parseObject(data, type);
		} catch (Exception e) {
			Log.w(TAG, "json2Object error:", e);
			if (isShowToast) {
				sendMessage(context.toString(), HttpResult.API_RESULT_FAILED);
			}
		}
		return resultObject;
	}

}